Burn Severity • Wildfire Analysis • Remote Sensing

RdNBR – Relative differenced Normalized Burn Ratio

RdNBR is a burn severity index that compares pre-fire and post-fire NBR and scales the difference by the pre-fire condition. It is widely used in wildfire impact assessment and post-fire recovery monitoring. Sensor-independent • NIR & SWIR2

1. Scientific Background & Concept

The Relative differenced Normalized Burn Ratio (RdNBR) is a post-fire index designed to quantify burn severity by comparing pre-fire and post-fire conditions derived from the Normalized Burn Ratio (NBR).

Base Index: NBR

NBR enhances the contrast between healthy vegetation and burned areas using the Near Infrared (NIR) and Shortwave Infrared (SWIR2) bands:

NBR = (NIR − SWIR2) / (NIR + SWIR2)

RdNBR Definition

RdNBR introduces a relative scaling that accounts for the pre-fire fuel condition (pre-fire NBR), making severity more comparable across areas with different vegetation densities:

RdNBR = (NBRpre − NBRpost) / √|NBRpre| Dimensionless (typically −2 to > +2)

Higher positive RdNBR values indicate stronger spectral changes associated with high burn severity, while values near zero represent unchanged or unburned areas. Negative values may reflect regrowth, increased vegetation, or noise.

Typical Interpretation (Approximate)

RdNBR Range Interpretation
< 0.0 Vegetation gain / regrowth / increased greenness
0.0 – 0.1 Unburned or very low change
0.1 – 0.44 Low burn severity
0.44 – 0.74 Moderate burn severity
> 0.74 High to extreme burn severity

Main Use Cases

  • Mapping wildfire burn severity at local to regional scales
  • Supporting post-fire management, restoration, and risk assessment
  • Comparing fire impact across different ecosystems and fuel types
  • Time-series analysis of disturbance and recovery dynamics

2. Data & Bands for RdNBR

Common Sensors & Bands

  • Sentinel-2 (ESA) – 10–20 m
    • NIR: B8 (~842 nm)
    • SWIR2: B12 (~2190 nm)
  • Landsat 8/9 OLI – 30 m
    • NIR: B5
    • SWIR2: B7

Temporal Windows

For RdNBR, you need two periods:

  • Pre-fire composite: before the wildfire event.
  • Post-fire composite: shortly after the fire (same season if possible).

Good Practice

  • Use surface reflectance products with atmospheric correction.
  • Apply cloud and cloud-shadow masking (e.g., using SCL for Sentinel-2).
  • Keep pre- and post-fire periods as close as possible in seasonality.
  • Clip to the area of interest (AOI) and check histograms to adjust classification thresholds.

Typical Output

RdNBR is often visualized with a diverging color palette, where low or negative values are shown in cool colors (e.g., blues) and high burn severity in warm colors (e.g., oranges to reds).

Output: RdNBR (float, continuous)

3. Google Earth Engine Code – RdNBR (Pre- vs Post-fire)

Steps: open code.earthengine.google.com → New Script → paste the code → draw your AOI as geometry on the map → click Run. Then adjust the pre- and post-fire dates and export RdNBR as GeoTIFF to Google Drive.

// RdNBR (Relative differenced Normalized Burn Ratio) with Sentinel-2 SR
// ---------------------------------------------------------------------
// This script computes pre-fire NBR, post-fire NBR and RdNBR for any AOI.
// Sensor: Sentinel-2 Level-2A (Surface Reflectance)
//
// HOW TO USE:
// 1) Go to: https://code.earthengine.google.com
// 2) Click "New Script" and paste this code.
// 3) On the map: draw your AOI (Polygon/Rectangle).
//    It will appear as a variable named 'geometry' in the left panel.
// 4) Set pre-fire and post-fire date ranges for your event.
// 5) Click "Run" to display RdNBR.
// 6) In the Tasks tab, click "Run" to export RdNBR to Google Drive.

// -------------------------------------------------------
// 1. Define Area of Interest (AOI)
// -------------------------------------------------------
var roi = geometry;  // Make sure a 'geometry' object exists in the left panel

// Center the map on the AOI
Map.centerObject(roi, 10);

// -------------------------------------------------------
// 2. Define pre-fire and post-fire date ranges
// -------------------------------------------------------
// EXAMPLE: adjust dates based on the wildfire event you are studying
var preStart  = '2022-05-01';
var preEnd    = '2022-07-01';
var postStart = '2022-08-01';
var postEnd   = '2022-10-01';

// -------------------------------------------------------
// 3. Cloud masking function for Sentinel-2 SR
// -------------------------------------------------------
function maskS2SR(img) {
  // Use the SCL band for basic cloud/cloud-shadow masking
  var scl = img.select('SCL');
  // Keep vegetation, bare soil, water, and unclassified (4,5,6,7,11)
  var mask = scl.eq(4).or(scl.eq(5)).or(scl.eq(6)).or(scl.eq(7)).or(scl.eq(11));
  
  return img
    .updateMask(mask)
    // Keep NIR (B8) and SWIR2 (B12), scaled to reflectance
    .select(['B8', 'B12'])
    .divide(10000)
    .copyProperties(img, img.propertyNames());
}

// -------------------------------------------------------
// 4. Build pre-fire and post-fire composites
// -------------------------------------------------------
var s2 = ee.ImageCollection('COPERNICUS/S2_SR')
  .filterBounds(roi);

// Pre-fire composite
var preCol = s2
  .filterDate(preStart, preEnd)
  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 60))
  .map(maskS2SR);

var preImg = preCol.median().clip(roi);

// Post-fire composite
var postCol = s2
  .filterDate(postStart, postEnd)
  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 60))
  .map(maskS2SR);

var postImg = postCol.median().clip(roi);

// -------------------------------------------------------
// 5. Compute NBR (pre and post)
// -------------------------------------------------------
// NBR = (NIR - SWIR2) / (NIR + SWIR2)
var nbrPre  = preImg.normalizedDifference(['B8', 'B12']).rename('NBR_pre');
var nbrPost = postImg.normalizedDifference(['B8', 'B12']).rename('NBR_post');

// -------------------------------------------------------
// 6. Compute RdNBR
// -------------------------------------------------------
// RdNBR = (NBR_pre - NBR_post) / sqrt(|NBR_pre|)
var rdnbr = nbrPre.subtract(nbrPost)
  .divide(nbrPre.abs().sqrt())
  .rename('RdNBR');

// Stack all indices if needed
var stack = nbrPre.addBands(nbrPost).addBands(rdnbr);

// -------------------------------------------------------
// 7. Visualization parameters
// -------------------------------------------------------
var nbrVis = {
  min: -1,
  max: 1,
  palette: [
    '#313695', '#4575b4', '#74add1', '#abd9e9',
    '#e0f3f8', '#ffffbf', '#fee090', '#f46d43',
    '#d73027', '#a50026'
  ]
};

var rdnbrVis = {
  min: -0.5,
  max: 1.5,
  palette: [
    '#313695', '#4575b4', '#74add1', '#e0f3f8',
    '#ffffbf', '#fee08b', '#f46d43', '#d73027', '#a50026'
  ]
};

// -------------------------------------------------------
// 8. Add layers to the map
// -------------------------------------------------------
Map.addLayer(nbrPre, nbrVis,  'NBR pre-fire', false);
Map.addLayer(nbrPost, nbrVis, 'NBR post-fire', false);
Map.addLayer(rdnbr, rdnbrVis, 'RdNBR (burn severity)', true);

// Optional: also display a true color composite for reference
var s2_rgb = ee.ImageCollection('COPERNICUS/S2_SR')
  .filterBounds(roi)
  .filterDate(preStart, postEnd)
  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 40))
  .select(['B4','B3','B2'])  // RGB
  .median()
  .clip(roi);

Map.addLayer(s2_rgb, {min:0, max:3000}, 'True Color (RGB)', false);

// -------------------------------------------------------
// 9. Export RdNBR as GeoTIFF to Google Drive
// -------------------------------------------------------
Export.image.toDrive({
  image: rdnbr,
  description: 'RdNBR_Export',
  fileNamePrefix: 'RdNBR_Export',
  region: roi,
  scale: 20,        // Sentinel-2 native resolution for NIR/SWIR
  maxPixels: 1e13,
  crs: 'EPSG:4326'
});